package com.sojson.websocket.config;

import org.springframework.stereotype.Component;

import com.sojson.util.HexUtil;
import com.sojson.websocket.util.WebSocketPoolUtil;
import com.sojson.websocket.util.bean.WebSocketConnect;
import com.sojson.websocket.util.enums.EElectricType;
import com.sojson.websocket.util.enums.EWebSocketDataType;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

/**
 * WebSocket处理器
 *
 * @author liu
 * @date 2024-05-28
 */
@Slf4j
@Sharable
@Component
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /**
     * 建立连接时触发的方法
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    /**
     * 关闭连接时触发的方法
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Object object = ctx.channel().attr(AttributeKey.valueOf(WebSocketPoolUtil.ADDR_KEY)).get();
        String addr = null;
        if (object != null) {
            addr = object.toString();
            // 从连接池中删除
            WebSocketPoolUtil.remove(addr);
        }
        super.channelInactive(ctx);
    }

    /**
     * 发生错误时触发的方法
     *
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
        Object object = ctx.channel().attr(AttributeKey.valueOf(WebSocketPoolUtil.ADDR_KEY)).get();
        String addr = null;
        if (object != null) {
            addr = object.toString();
        }
        log.error(new StringBuilder("WebSocket连接发生错误: ").append(addr).append(",").append(e.getMessage()).toString());
        log.error(e.getMessage(), e);
    }

    /**
     * 收到消息后执行的方法
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        log.info(msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("1111111111111"));
    }

    public void run(ChannelHandlerContext ctx, EWebSocketDataType type, String data) throws Exception {
        String addr = null;
        String addrRever = null;

        // 分类处理
        if (type == EWebSocketDataType.HEARTBEAT_485) {
            // 采集器
            addr = data.substring(4, 18);
            addrRever = HexUtil.reverse(addr).replaceFirst("^0*", "");

            log.info(new StringBuilder("WebSocket收到采集器心跳包: ").append(addrRever).append(",").append(data).toString());
            WebSocketConnect connect = WebSocketPoolUtil.get(addrRever);
            if (connect == null) {
                WebSocketPoolUtil.put(EElectricType.HARVESTER, addrRever, ctx);
            } else if (connect.getCtx() == null) {
                WebSocketPoolUtil.put(EElectricType.HARVESTER, addrRever, ctx);
            }
        } else {
            // 4G电表
            if (type == EWebSocketDataType.REGISTER) {
                // 注册包
                addr = data.substring(12, 24);
                addrRever = HexUtil.reverse(addr);

                log.info(
                    new StringBuilder("WebSocket收到电表注册包: ").append(addrRever).append(",").append(data).toString());
            } else if (type == EWebSocketDataType.HEARTBEAT) {
                // 心跳包
                addr = data.substring(12, 24);
                addrRever = HexUtil.reverse(addr);

                log.info(
                    new StringBuilder("WebSocket收到电表心跳包: ").append(addrRever).append(",").append(data).toString());
            } else if (type == EWebSocketDataType.BUSINESS) {
                addr = data.substring(2, 14);
                addrRever = HexUtil.reverse(addr);

                // 业务包
            } else {
            }
        }
    }

}